<?php
/* 
 * Count investment candidate votes, processing the winner accordingly.
 * Increment the system month then generate 3 new candidates from the pool
 * of upcoming investment candidates.
 *
 * OPTIONS
 * -i       continue silently if no candidates present
 */

require_once('environment.php');
require_once('simulation.php');
require_once('lib.php');
require_once('data_access.php');

init_environment();

$this_month = read_this_month();
if (!$candidates = read_candidates($this_month)) {
    if (!in_array('-i', $argv)) {
        throw new Exception('No candidates to choose from');
    }
} else {
    $winner = get_winning_candidate($candidates, $this_month);

    foreach ($candidates as &$candidate) {
        if ($candidate['id'] != $winner['id']) {
            $candidate['type'] = INVESTMENT_TYPE_REJECTED;
            update_investment($candidate);
        }
    }

    // ***
    $winner['amount'] = 100;
    $winner['type'] = INVESTMENT_TYPE_COMPLETE;
    update_investment($winner);
    // ***

    $key = month_to_cassandra_key($this_month);

    // ***
    
    //$_TABLES[TABLE_BLOG]->insert($key, array($winner['id'] => 1));
    write_blog($key, array($winner['id'] => 1));

    // ***

    $next_month = advance_current_month();
}
pick_candidates_from_upcoming();

/**
 * Advance the current month (as stored in cassandra) forward by one month.
 * This doesn't present a race-condition as only a single thread will ever
 * be invoking the code.
 */
function advance_current_month() {
    $this_month = read_this_month();
    $next_month = strtotime(date('Y-m', $this_month) . ' +1 month'); // as timestamp
    $next_month = date('Y-m', $next_month); // as string
    $environment = read_environment();
    $environment['month'] = $next_month;
    write_environment($environment);
    return $next_month;
}

/**
 * From a list of candidate arrays return the candidate with the most votes.
 * @param array list of candidates, each containing a votes property
 * @return array one of the candidates
 */
function get_winning_candidate($candidates, $this_month) {

    $votes = read_votes($this_month);

    // TODO check the same user didn't vote for two different investments

    // get the highest number of votes
    $max_votes = 0;
    foreach ($votes as $vote) {
        $max_votes = max($max_votes, count($vote));
    }

    // remove all candidates receiving less than max votes
    $winners = array_filter($votes, function($vote) use ($max_votes) {
        return count($vote) == $max_votes;
    });

    // pick randomly from the winners
    return $candidates[array_rand($winners)];
}

/**
 * Pick 3 random upcoming investments candidates and set them as candidates
 * for next month's voting.
 */
function pick_candidates_from_upcoming() {

    // Read all upcoming investments
    if (!$upcoming_investments = read_upcoming_investments()) {
        throw new Exception('No upcoming investment candidates');
    }
    if (count($upcoming_investments) < 3) {
        throw new Exception('No enough investment candidates');
    }

    /* Pick 3 upcoming investments at random; dropping each selected candidate
     * from the upcoming investments database table and writing the candidate
     * to the live investments table.
     * *** SHOULD BE DONE IN A TRANSACTION *** */
    foreach (array_rand($upcoming_investments, 3) as $candidate_ordinal) {
        $candidate = $upcoming_investments[$candidate_ordinal];

        drop_investment_from_index($candidate['id']);

        $candidates[] = $candidate;
        $candidate['proposed'] = read_this_month();
        $candidate['type'] = INVESTMENT_TYPE_PROPOSED;
        update_investment($candidate);
    }

    // Store candidates for current month in blog
    foreach ($candidates as $candidate) {
        $record[$candidate['id']] = 0;
    }
    $key = month_to_cassandra_key(read_this_month());
    write_blog($key, $record);

}

?>
